
Skt.History = L.Class.extend({
	
	events: [],

	initialize: function(room, execute, rollback) {
	  
		this._room = room;
	 
		this._undoStack = [];
		this._redoStack = [];
		this._waitingQueue = [];
    
		this._execute = this._isFn(execute, "initialize") ? execute : function() {};
		this._rollback = this._isFn(rollback,"initialize") ? rollback : function() {};
    
		this._couple(this._room.getRoomList().getSketchpad().getOptions().coupling);
	},

	addCommand: function(command) {
		var self = this;
		// verificar que no es un tipo usado internamente por History
		if(command.type == '_undo_' || command.type == '_redo_'){
			console.log('[WARNING] L.History.addCommand no se puede utilizar command.type _undo_ o _redo_');
		}
		
		command['id']= new ObjectId().toString();
		command['roomId'] = self._room.getId();
		
		//se ejecuta inmediatamente el comando y se pone en la cola de espera por confirmacion.
		if(command.type != "ping") {
			self._executeCommand(command);
			self._waitingQueue.push(command);
		}
	},

	undo: function() {
		var self = this;
		if (self.undoable()) {
			// enviar comando al servidor.
			var command = {
				id: new ObjectId().toString(),
				type: '_undo_',
				roomId: self._room.getId()
			};
			self._executeCommand(command);
		}
	},

	redo: function() {
		var self = this;
		if (self.redoable()) {
			// enviar comando al servidor
			var command = {
				id: new ObjectId().toString(),
				type: '_redo_',
				roomId: self._room.getId()
			};
			self._executeCommand(command);
		}    
	},

	undoable: function() {
		return this._undoStack.length > 0;
	},

	redoable: function() {
		return this._redoStack.length > 0;
	},

	_executeCommand: function(command) { 
		var self = this;
		var us = self._undoStack;
		var rs = self._redoStack;

		switch (command.type) {
		case '_undo_':
			var lastCommand = us.pop();
			rs.push(lastCommand);
			self._rollback(lastCommand);
			break;
		case '_redo_':
			var lastCommand = rs.pop();
			us.push(lastCommand);
			self._execute(lastCommand);
			break;
		default:
			us.push(command);
			self._execute(command);
		}
	},

	_isFn: function(fn, FName, echoOff) {
		var is = typeof fn == 'function';
		if (!is && !echoOff)
			console.log('[WARNING] L.History.' + FName + ' fn no es una funcion');
		return is;
	},
  
	_couple: function( coupling ) {
		if ( coupling.enabled  ) {
			var adapter = coupling.activityAdapter;
			if ( this._room.getType() == Skt.SlideType.PERSONAL )
				adapter = coupling.personalAdapter;
			
			adapter.coupleObject(
				"roomhistory-" + this._room.getId(),
				this,
				{
					explicitMapping:[ "addCommand", "undo", "redo"],
					messageType:"EVENT"
				}
			);
		}
  },

});

Skt.History.findSelf = function(history) {
	return Skt.sketchpad.findRoomById(history._room._id).getHistory();
};

